package com.solome.base;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.StringBuilder;
import com.solome.device.IConfig;
import com.solome.device.IInput;
import com.solome.util.InvokeFactory;

/**
 * 椤甸潰鍩虹被
 * 
 * @author soells
 *
 */
public abstract class AbstractScreen extends Stage implements Screen, IInput {
	protected Game game;
	protected boolean paused;
	private boolean debugGameInfo;
	// protected BitmapFontCache cache;
	protected float elapsed;
	protected InvokeFactory factory = new InvokeFactory();
	int minFps;

	public AbstractScreen(Game game) {
		super(IConfig.viewport, new SpriteBatch());
		this.game = game;
	}

	@Override
	public void show() {
		// TODO Auto-generated method stub
		// stage = new Stage();
		// if (cache != null) {
		// cache.clear();
		// }
		// cache = new BitmapFontCache(new BitmapFont());
		// {
		// }
		this.init();
	}

	@Override
	public void render(float delta) {
		// TODO Auto-generated method stub
		if (minFps == 0 || minFps > Gdx.graphics.getFramesPerSecond()) {
			minFps = Gdx.graphics.getFramesPerSecond();
		}
		elapsed += delta;
		Gdx.gl20.glClearColor(0, 0, 0, 0);
		Gdx.gl20.glClear(GL30.GL_COLOR_BUFFER_BIT);
		if (this != null) {
			if (debugGameInfo) {
				Label fps = this.getRoot().findActor("fps");

				StringBuilder builder = new StringBuilder();
				if (fps != null)
					builder.append("FPS:" + Gdx.graphics.getFramesPerSecond());
				if (minFps > 0) {
					builder.append("     MINFPS:" + minFps);
				}
				fps.setText(builder.toString());

			}
			this.act(delta);
			this.draw();
			this.getBatch().begin();
			this.draw(delta);
			this.getBatch().end();
		}
		factory.invoke();
	}

	public void add(Object actor) {
		if (actor instanceof Actor) {
			this.addActor((Actor) actor);
		} else if (actor instanceof Action) {
			this.addAction((Action) actor);
		} else if (actor instanceof Texture) {
			Image bg = new Image((Texture) actor);
			this.addActor(bg);
		} else
			throw new IllegalStateException("Object error.");
	}

	public void add(Actor actor) {
		this.addActor(actor);
	}

	public void add(Actor actor, int tag) {
		actor.setName("" + tag);
		this.add(actor);
	}

	public void add(Action action) {
		this.addAction(action);
	}

	public void add(Action action, Actor actor) {
		action.setActor(actor);
		this.addAction(action);
	}

	public Object get(int tag) {
		return this.getRoot().findActor("" + tag);
	}

	public void remove(int tag) {
		Object actor = get(tag);
		if (actor != null) {
			if (actor instanceof Actor) {
				this.getRoot().removeActor((Actor) actor);
			} else if (actor instanceof Action) {
				this.getRoot().removeAction((Action) actor);
			} else
				throw new IllegalStateException("Object error.");
		}
	}

	@Override
	public void resize(int width, int height) {
		// TODO Auto-generated method stub
		this.getViewport().update(width, height);
		getBatch().setTransformMatrix(this.getCamera().view);
		getBatch().setProjectionMatrix(this.getCamera().projection);
	}

	@Override
	public void hide() {
		// TODO Auto-generated method stub
		System.out.println("hide");
		for (Actor actor : this.getRoot().getChildren()) {
			if (actor instanceof Disposable) {
				Disposable disposable = (Disposable) actor;
				disposable.dispose();
			}
		}

		for (Action action : this.getRoot().getActions()) {
			if (action instanceof Disposable) {
				Disposable disposable = (Disposable) action;
				disposable.dispose();
			}
		}
		this.getRoot().clear();
		super.dispose();
		this.free();
		this.factory.dispose();

	}

	@Override
	public void dispose() {
		super.dispose();
	}

	/**
	 */
	protected void setInputAdapter() {
		Gdx.input.setInputProcessor(this);
	}

	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		if (super.touchDown(screenX, screenY, pointer, button)) {
			return false;
		}
		return this.onTouchDown(screenX, screenY, pointer, button);
	}

	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
		if (super.touchUp(screenX, screenY, pointer, button)) {
			return false;
		}
		return this.onTouchUp(screenX, screenY, pointer, button);
	}

	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		// TODO Auto-generated method stub
		if (super.touchDragged(screenX, screenY, pointer)) {
			return false;
		}
		return this.onTouchMove(screenX, screenY, pointer);
	}

	abstract public void init();

	public void draw(float delta) {
	};

	abstract public void free();

	public boolean onTouchDown(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	public boolean onTouchUp(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	public boolean onTouchMove(int screenX, int screenY, int pointer) {
		return false;
	}

	public boolean isDebugGameInfo() {
		return debugGameInfo;
	}

	public void setDebugGameInfo(boolean debugGameInfo) {
		this.debugGameInfo = debugGameInfo;
		this.setDebugAll(debugGameInfo);
		// this.setDebugInvisible(debugGameInfo);
		// this.setDebugParentUnderMouse(debugGameInfo);
		// this.setDebugTableUnderMouse(debugGameInfo);
		// this.setDebugUnderMouse(debugGameInfo);
		Label fps = new Label("", new LabelStyle(new BitmapFont(), Color.WHITE));
		fps.setColor(Color.RED);
		fps.setName("fps");
		fps.setPosition(5, 15);
		this.add(fps);
	}

	public Game getGame() {
		return game;
	}

	public void setGame(Game game) {
		this.game = game;
	}

}
